Spring @Autowired+@Qualifier与@Resource的区别

最近由于希望使用Spring在XML文件中定义List的bean,并使用@Autowired进行注入到对象中使用,遇到到一些坑,记录一下作为备忘。

@Autowired

@Autowired是Spring定义的注解,是根据类型进行自动装配的。如果当spring上下文中存在不止一个存在一个需要装配类型的bean时,就会抛出BeanCreationException异常;这时我们可以使用@Qualifier配合@Autowired来解决问题。

@Resource

@Resource是JSR-250规定的注解,主要有两种类型的属性type及name,所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略
@Resource装配顺序:

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

使用区别

使用Spring注入List的时候在XML中定义:

1
2
3
4
<util:list id="myList">
<value>10.1.200.104</value>
<value>10.1.200.205</value>
</util:list>

之后使用注解注入,代码1为:

1
2
3
4
5
@Component
public class App {
@Autowired
List list;
}

注入失败。修改,代码2为:

1
2
3
4
5
@Component
public class App {
@Autowired
ArrayList<String> strings;
}

注入仍然失败。修改,代码3为:

1
2
3
4
5
6
@Component
public class App {
@Autowired
@Qualifier('myList')
ArrayList<String> strings;
}

仍然失败。主要原因在于,使用Autowired注入,Spring默认使用按类型方式注入,而对于List集合类型Spring会读取其中的泛型类型进行注入,上面代码2的含义为注入当前bean中类型为String的对象,代码3的含义为注入当前bean中类型为String且qualifier是myList的对象。这两种含义都不能完成正确的注入。

正确使用

使用@Resource注入,引用stackoverflow上的解答使用正确方式为:

1
2
3
4
5
6
7
@Component
public class App {

@Resource(name = "myList")
ArrayList<Object> list;

}

或者

1
2
3
4
5
6
7
@Component
public class App {

@Resource(name = "myList")
List<Object> list;

}

因为Resource设置了name属性,Spring直接寻找id为myList的对象进行注入,可以注入成功。